#define _GNU_SOURCE
#include "app_serial.h"


/**
 * @brief 串口的初始化
 * @return int 0:成功, -1:失败
 */
int app_serial_init(device_t *device)
{
    int ret = app_serial_set_baud(device,BR_9600);
    if(ret == -1)
    {
        perror("设置波特率 错误");
        return -1;
    }
    ret = app_serial_set_check(device,PARITY_NONE);
    if(ret == -1)
    {
        perror("设置校验位 错误");
        return -1;
    }
    ret = app_serial_set_stop(device,STOP_BIT_ONE);
    if (ret == -1)
    {
        perror("设置停止位 错误");
        return -1;
    }
    ret = app_serial_set_makeraw(device);
    if (ret == -1)
    {
        perror("还原原始设置 错误");
        return -1;
    }

    // 要执行flash
    ret = tcflush(device->dev_fd, TCIOFLUSH);
    if (ret == -1)
    {
        perror("执行tcflush 错误");
        return -1;
    }

    return 0;
}


/**
 * @brief 波特率设置
 * @param baud 波特率
 * @return int 0:成功, -1:失败
 * @note 取出termios的结构体 \
 * 设值 \
 * 写入
 */
int app_serial_set_baud(device_t *device,SERIAL_BAUD_RATE baud)
{
    // 取出termios的结构体 
    struct termios termios_attr;
    int ret = tcgetattr(device->dev_fd, &termios_attr);
    if(ret == -1)
    {
        perror("tcgetattr 错误");
        return -1;
    }
    // 设值 
    cfsetspeed(&termios_attr,baud);
    // 写入
    ret = tcsetattr(device->dev_fd, TCSAFLUSH, &termios_attr);
    if(ret == -1)
    {
        perror("tcsetattr 写入错误");
        return -1;
    }
    return 0;
}
 
/**
 * @brief 校验位
 * @param check 校验位
 * @return int 0:成功, -1:失败
 */
int app_serial_set_check(device_t *device,SERIAL_PARITY check)
{
    // 取出termios的结构体 
    struct termios termios_attr;
    int ret = tcgetattr(device->dev_fd, &termios_attr);
    if(ret == -1)
    {
        perror("tcgetattr 错误");
        return -1;
    }
    // 设值 
    termios_attr.c_cflag &= ~PARITY_ODD;
    termios_attr.c_cflag |= check;
    // 写入
    ret = tcsetattr(device->dev_fd, TCSAFLUSH, &termios_attr);
    if(ret == -1)
    {
        perror("tcsetattr 写入错误");
        return -1;
    }
    return 0;
}

/**
 * @brief 停止位
 * @param stop 停止位
 * @return int 0:成功, -1:失败
 */
int app_serial_set_stop(device_t *device,SERIAL_STOP_BIT stop)
{
    // 取出termios的结构体 
    struct termios termios_attr;
    int ret = tcgetattr(device->dev_fd, &termios_attr);
    if(ret == -1)
    {
        perror("tcgetattr 错误");
        return -1;
    }
    // 设值 
    termios_attr.c_cflag &= ~CSTOPB;
    termios_attr.c_cflag |= stop;
    // 写入
    ret = tcsetattr(device->dev_fd, TCSAFLUSH, &termios_attr);
    if(ret == -1)
    {
        perror("tcsetattr 写入错误");
        return -1;
    }
    return 0;
}

/**
 * @brief 设置原始模式
 * @return int 0:成功, -1:失败 
 */
int app_serial_set_makeraw(device_t *device)
{
    // 取出termios的结构体 
    struct termios termios_attr;
    int ret = tcgetattr(device->dev_fd, &termios_attr);
    if(ret == -1)
    {
        perror("tcgetattr 错误");
        return -1;
    }
    // 设值 
    cfmakeraw(&termios_attr);
    // 写入
    ret = tcsetattr(device->dev_fd, TCSAFLUSH, &termios_attr);
    if(ret == -1)
    {
        perror("tcsetattr 写入错误");
        return -1;
    }
    return 0;
}

/**
 * @brief 设置是否阻塞模式
 * @param block 0:非阻塞, 1:阻塞
 * @return int 0:成功, -1:失败
 */
int app_serial_set_block(device_t *device,int block)
{
    // 取出termios的结构体 
    struct termios termios_attr;
    int ret = tcgetattr(device->dev_fd, &termios_attr);
    if(ret == -1)
    {
        perror("tcgetattr 错误");
        return -1;
    }
    // 设值 
    // 设置阻塞模式
    if(block)
    {
        // 设置阻塞模式 日常使用
        termios_attr.c_cc[VTIME] = 0;
        termios_attr.c_cc[VMIN] = 1;
    }
    else
    {
        // 设置非阻塞模式 dubug模式
        termios_attr.c_cc[VTIME] = 2; // 设置超时时间为200毫秒
        termios_attr.c_cc[VMIN] = 0;
    }
    // 写入
    ret = tcsetattr(device->dev_fd, TCSANOW, &termios_attr);
    if(ret == -1)
    {
        perror("tcsetattr 写入错误");
        return -1;
    }
    return 0;
}